package com.demo.webapp.listener;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.demo.core.model.Site;
import com.demo.core.service.base.SiteService;
import com.demo.webapp.config.Constants;
import com.demo.webapp.security.method.access.intercept.MultisitePersistentMethodSecurityMetadataSource;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 初始化容器监听器<br>
 * 对web容器所需要的内容进行处理
 * 
 * @author ryuu.kk
 *
 */
public abstract class StartupListener implements ServletContextListener {
	
	/**日志对象**/
    private static final Log LOG = LogFactory.getLog(StartupListener.class);
	
    /**
     * 应用容器上下文
     */
    private ApplicationContext applicationContext;
    
    /**
     * 站点配置信息 
     */
    private Map<String, Object> config;
    
    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    public void contextInitialized(ServletContextEvent event) {
    	if (LOG.isDebugEnabled()) {
    		LOG.debug("Initializing context...");
    	}
        ServletContext context = event.getServletContext();
        //该listener需要在spring的org.springframework.web.context.ContextLoaderListener之后
        applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(context);
        
        //站点基础配置属性模型对象(多站点)
        config = (Map<String, Object>) context.getAttribute(Constants.CONFIG);
        if (config == null) {
            config = new HashMap<String, Object>();
        }
        
    	if (LOG.isDebugEnabled()) {
    		LOG.debug("/*************************************************************");
    		LOG.debug(" *");
    		LOG.debug(" *   系统启动 @基本数据加载.");
    		LOG.debug(" *");
    	}
        
        // 得到Application上下文容器
        ApplicationContext ctx = getApplicationContext();
        
        SiteService siteService = ctx.getBean("siteService", SiteService.class);
    	List<Site> siteList = siteService.findAll();
    	
    	for(int i = 0; i < siteList.size(); i++) {
    		Site site = siteList.get(i);
    		// 创建站点的基础配置Map
    		Map<String, Object> siteConfig = new HashMap<String, Object>();
        	if (LOG.isDebugEnabled()) {
        		LOG.debug(" *   " + i + "、发现站点:" + site.getName() + " @" + site.getDomain());
        		LOG.debug(" *     ▪ 加载" + site.getName() + "站点基本配置信息");
        	}
        	// 加载站点资源路径
        	
        	
        	//取得初始化主题
            if (context.getInitParameter(Constants.CSS_THEME) != null) {
            	siteConfig.put(Constants.CSS_THEME, context.getInitParameter(Constants.CSS_THEME));
            	if (LOG.isDebugEnabled()) {
            		LOG.debug(" *     ▪ 加载主题 " + context.getInitParameter(Constants.CSS_THEME) + " 信息.");
            	}
            }

            //增加自定义指令配置读取
            if (context.getInitParameter(Constants.CUSTOM_DIRECTIVE) != null) {
            	siteConfig.put(Constants.CUSTOM_DIRECTIVE, context.getInitParameter(Constants.CUSTOM_DIRECTIVE));
            	if (LOG.isDebugEnabled()) {
            		LOG.debug(" *     ▪ 加载指令 Path: " + context.getInitParameter(Constants.CUSTOM_DIRECTIVE));
            	}
            }
            
            siteConfig = onSiteInitialized(site, siteConfig);
            // 
            config.put(site.getDomain(), siteConfig);
    	}
    	
    	if (LOG.isDebugEnabled()) {
    		LOG.debug("************************************************************ */");
    	}
    	// 增加站点功能的访问控制列表
        MultisitePersistentMethodSecurityMetadataSource metadataSource = applicationContext.getBean("multisitePersistentMethodSecurityMetadataSource", MultisitePersistentMethodSecurityMetadataSource.class);
        
        if (metadataSource != null) {
        	config.put(Constants.CONFIG_FUNCTION_ACL, metadataSource.getMultisiteSerucityMetadataMap());
        } else {
        	LOG.warn("not found MultisitePersistentMethodSecurityMetadataSource in ApplicationContext.");
        }
        
    	context.setAttribute(Constants.CONFIG, config);
        //setupContext(context);
    }

    /**
     * 每站点加载的个性处理
     * 
     * @return Map<String, Object>
     */
    protected abstract Map<String, Object> onSiteInitialized(Site site, Map<String, Object> siteConfig);
    
    /**
     * 析构函数
     * @param ServletContextEvent application应用上下文事件
     */
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        LogFactory.release(Thread.currentThread().getContextClassLoader());
        //Commented out the above call to avoid warning when SLF4J in classpath.
        //WARN: The method class org.apache.commons.logging.impl.SLF4JLogFactory#release() was invoked.
        //WARN: Please see http://www.slf4j.org/codes.html for an explanation.
    }

	protected ApplicationContext getApplicationContext() {
		return applicationContext;
	}
	
	protected Map<String, Object> getConfig() {
		return this.config;
	}
}
